﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Helpers;
using System.Web.Security;
using Monocle.DataModel;
using Monocle.DataProvider;

namespace Monocle.Infrastructure.Account
{
    public class AccountMembershipProvider : MembershipProvider
    {
        private SqlClient dataProvider;
        public AccountMembershipProvider()
        {
            dataProvider = AccountDataAccess.DataProvider();
        }

        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            if (string.IsNullOrEmpty(username))
            {
                status = MembershipCreateStatus.InvalidUserName;
                return null;
            }
            if (string.IsNullOrEmpty(password))
            {
                status = MembershipCreateStatus.InvalidPassword;
                return null;
            }
            if (string.IsNullOrEmpty(email))
            {
                status = MembershipCreateStatus.InvalidEmail;
                return null;
            }

            string HashedPassword = Crypto.HashPassword(password);
            if (HashedPassword.Length > 128)
            {
                status = MembershipCreateStatus.InvalidPassword;
                return null;
            }
            if(dataProvider.GetUserByEmail(email) != null)
            {
                 status = MembershipCreateStatus.DuplicateEmail;
                return null;
            }

            var user = new tUser
                           {
                               Email = email,
                               PK_tUser = Guid.NewGuid(),
                               Password = HashedPassword,
                               IsApproved = isApproved,
                               CreatedDate = DateTime.UtcNow,
                               LastLoginDate = DateTime.UtcNow,
                               LastActivityDate = DateTime.UtcNow,
                               LastLockoutDate = DateTime.UtcNow,
                               IsLockedOut = false,
                               LastPasswordChangedDate = DateTime.UtcNow
                           };

            user = dataProvider.SaveUser(user);
            if(user.Version != null)
            {
                status = MembershipCreateStatus.Success;
                return new MembershipUser(Membership.Provider.Name, user.Email, user.PK_tUser, user.Email, null, null, user.IsApproved, user.IsLockedOut, user.CreatedDate, user.LastLoginDate, user.LastActivityDate, user.LastPasswordChangedDate, user.LastLockoutDate);
            }

            status = MembershipCreateStatus.UserRejected;
            return null;

        }

        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            throw new NotImplementedException();
        }

        public override string GetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override bool ChangePassword(string email, string oldPassword, string newPassword)
        {
            if (string.IsNullOrEmpty(email))
            {
                return false;
            }
            if (string.IsNullOrEmpty(oldPassword))
            {
                return false;
            }
            if (string.IsNullOrEmpty(newPassword))
            {
                return false;
            }
            var user = dataProvider.GetUserByEmail(email);
            if (user == null)
            {
                return false;
            }
            var version = user.Version;
            String HashedPassword = user.Password;
            Boolean VerificationSucceeded = (HashedPassword != null && Crypto.VerifyHashedPassword(HashedPassword, oldPassword));
            if (!VerificationSucceeded)
            {
                return false;
            }
            String NewHashedPassword = Crypto.HashPassword(newPassword);
            if (NewHashedPassword.Length > 128)
            {
                return false;
            }
            user.Password = NewHashedPassword;
            var newVersion = dataProvider.SaveUser(user).Version;
            return newVersion != version;
        }

        public override string ResetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override void UpdateUser(MembershipUser user)
        {
            throw new NotImplementedException();
        }

        public override bool ValidateUser(string email, string password)
        {
            if (string.IsNullOrEmpty(email))
            {
                return false;
            }
            if (string.IsNullOrEmpty(password))
            {
                return false;
            }
            var user = dataProvider.GetUserByEmail(email);
            String HashedPassword = user.Password;
            Boolean VerificationSucceeded = (HashedPassword != null && Crypto.VerifyHashedPassword(HashedPassword, password));
            if (VerificationSucceeded)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public override bool UnlockUser(string userName)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser GetUser(string email, bool userIsOnline)
        {
            if (string.IsNullOrEmpty(email))
            {
                return null;
            }
            var user = dataProvider.GetUserByEmail(email);
            return user != null ? new MembershipUser(Membership.Provider.Name,user.Email,user.PK_tUser,user.Email,null,null,user.IsApproved,user.IsLockedOut,user.CreatedDate,user.LastLoginDate,user.LastActivityDate,user.LastPasswordChangedDate,user.LastLockoutDate) : null;
        }

        public override string GetUserNameByEmail(string email)
        {
            throw new NotImplementedException();
        }

        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            throw new NotImplementedException();
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            var MembershipUsers = new MembershipUserCollection();
            var allUsers = dataProvider.GetUsers().AsQueryable();
            var users = allUsers.OrderBy(user => user.Email).Skip(pageIndex * pageSize).Take(pageSize);
            totalRecords = allUsers.Count();
            foreach (var user in users)
            {
                MembershipUsers.Add(new MembershipUser(Membership.Provider.Name, user.Email, user.PK_tUser, user.Email, null, null, user.IsApproved, user.IsLockedOut, user.CreatedDate, user.LastLoginDate, user.LastActivityDate, user.LastPasswordChangedDate, user.LastLockoutDate));
            }
            return MembershipUsers;
        }   

        public override int GetNumberOfUsersOnline()
        {
            throw new NotImplementedException();
        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override bool EnablePasswordRetrieval
        {
            get { throw new NotImplementedException(); }
        }

        public override bool EnablePasswordReset
        {
            get { throw new NotImplementedException(); }
        }

        public override bool RequiresQuestionAndAnswer
        {
            get { throw new NotImplementedException(); }
        }

        public override string ApplicationName
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public override bool RequiresUniqueEmail
        {
            get { throw new NotImplementedException(); }
        }

        public override MembershipPasswordFormat PasswordFormat
        {
            get { throw new NotImplementedException(); }
        }

        public override string PasswordStrengthRegularExpression
        {
            get { throw new NotImplementedException(); }
        }

        public override int MaxInvalidPasswordAttempts
        {
            get { return 5; }
        }

        public override int MinRequiredNonAlphanumericCharacters
        {
            get { return 0; }
        }

        public override int MinRequiredPasswordLength
        {
            get { return 5; }//TODO: Get from config
        }

        public override int PasswordAttemptWindow
        {
            get { return 0; }
        }

    }
}